package com.ruoyi.common.core.redis;

import java.util.concurrent.TimeUnit;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import com.ruoyi.common.utils.uuid.UUID;

/**
 *     分布式锁
     * @ClassName: RedisLockImpl
     * @Description: TODO(这里用一句话描述这个类的作用)
     * @author 顺哥
     * @date 2021年4月25日
     *
 */
@SuppressWarnings(value = { "unchecked", "rawtypes" }) 
@Component 
public class RedisLockImpl {

 	@Autowired
    public RedisTemplate redisTemplate;
    

	private ThreadLocal<String> threadLocal = new ThreadLocal<String>();

	private ThreadLocal<Integer> threadLocalInteger = new ThreadLocal<Integer>();

 	public boolean tryLock(String key, long timeout, TimeUnit unit) {
		boolean isLocked = false;
		if (threadLocal.get() == null) {
			String uuid = UUID.randomUUID().toString();
			threadLocal.set(uuid);
			isLocked = redisTemplate.opsForValue().setIfAbsent(key, uuid, timeout, unit);
 
			// TODO 如果获取失败，自旋锁，不停的尝试直达成功
			if (!isLocked) {
				for (;;) {
					isLocked = redisTemplate.opsForValue().setIfAbsent(key, uuid, timeout, unit);
					if (isLocked) {
						break;
					}

				}
			}
			//启动新线程来执行定时任务，更新锁过期时间
	        new Thread(new UpdateLockTimeoutTask(uuid, redisTemplate, key)).start();
			
		} else {
			isLocked = true;
		}

		// 加锁成功后
		if (isLocked) {
			Integer count = threadLocalInteger.get() == null ? 0 : threadLocalInteger.get();
			threadLocalInteger.set(count++);
		}
		


		return isLocked;
	}

	// TODO 解锁
 	public void releaseLock(String key) {
		if (threadLocal.get().equals(redisTemplate.opsForValue().get(key))) {
			Integer count = threadLocalInteger.get();
			if (count == null && --count <= 0) {
				redisTemplate.delete(key);
			}
		}

	}
}
